package com.av.client.frames;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDesktopPane;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.text.NumberFormatter;

import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.error.ErrorInfo;

import com.av.client.util.idioma.Error;
import com.av.client.util.idioma.Etiqueta;
import com.av.client.util.idioma.ManejadorIdiomas;
import com.av.client.util.idioma.ManejadorIdiomas.IdiomaEvent;
import com.av.client.util.idioma.ManejadorIdiomas.IdiomaEventListener;
import com.av.client.util.sesion.AdministradorSesion;
import com.av.db.dataobjects.ElementoCatalogo;
import com.av.db.dataobjects.enums.Catalogo;
import com.av.exceptions.AvException;
import com.av.rmi.CatalogoAcciones;
import com.av.rmi.Parametro;
import com.av.rmi.Parametro.Tipo;

@SuppressWarnings("serial")
public class ElementoCatalogoFrame extends JInternalFrame {

	private static final int WIDTH = 600;
	private static final int HEIGHT = 300;

	private JLabel lblDescripcion;
	private JTextField txtDescripcion;
	private JCheckBox chkActivo;
	private JLabel lblCatalogo;
	private JComboBox cboCatalogo;
	private JLabel lblMonto;
	private JFormattedTextField txtMonto;
	private JTable tblElementoCatalogo;
	private JButton btnAgregar;
	private JButton btnActualizar;
	private JButton btnEliminar;
	private JButton btnCerrar;
	private JButton btnObtenerCat;
	private JButton btnObtenerTodos;

	private ElementoCatalogoModel ecm;
	private ManejadorIdiomas mi;
	private BotonHandler bh = new BotonHandler();
	private ElementoCatalogo elementoSeleccionado;
	private ElementoCatalogo[] elementos;

	public ElementoCatalogoFrame() {
		super();
		mi = ManejadorIdiomas.getInstance();
		initComponents();
		addListeners();
		cargarElementoCatalogo();
		limpiarTextos();
	}// ElementoCatalogoFrame

	private void addListeners() {
		mi.addIdiomaEventListener(new IdiomaEventListener() {
			@Override
			public void changedIdiomaEvent(IdiomaEvent evt) {
				setLabels();
			}
		});

		tblElementoCatalogo.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {
					@Override
					public void valueChanged(ListSelectionEvent e) {
						if (elementos != null
								&& tblElementoCatalogo.getSelectedRow() >= 0
								&& tblElementoCatalogo.getSelectedRow() < elementos.length) {
							setElementoCatalogo(elementos[tblElementoCatalogo
									.getSelectedRow()]);
						}
					}
				});

		btnAgregar.addActionListener(bh);
		btnEliminar.addActionListener(bh);
		btnActualizar.addActionListener(bh);
		btnCerrar.addActionListener(bh);
		btnObtenerCat.addActionListener(bh);
		btnObtenerTodos.addActionListener(bh);
	}// addListeners

	/**
	 * Funcion que restablece las etiquetas para todos los componentes
	 */
	private void setLabels() {
		setTitle(mi.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_TITLE));
		lblDescripcion
				.setText(mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_LBL_DESCRIPCION));
		lblCatalogo
				.setText(mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_LBL_CATALOGO));
		lblMonto.setText(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_LBL_MONTO));
		txtMonto.setLocale(mi.getIdioma().getLocale());
		chkActivo.setText(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_CHK_ACTIVO));
		btnAgregar.setText(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_AGREGAR));
		btnEliminar
				.setText(mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_ELIMINAR));
		btnActualizar
				.setText(mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_ACTUALIZAR));
		btnCerrar.setText(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_CERRAR));
		btnObtenerCat
				.setText(mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_OBTENER_CAT));
		btnObtenerTodos
				.setText(mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_OBTENER_TODOS));
		String[] headers = (mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_TBL_ELEMENTOS_COLUMN_NAMES))
				.split(",");
		if (headers != null
				&& tblElementoCatalogo.getColumnCount() == headers.length) {
			for (int i = 0; i < tblElementoCatalogo.getColumnCount(); i++) {
				tblElementoCatalogo.getColumnModel().getColumn(i)
						.setHeaderValue(headers[i]);
			}
		}
	}// setLabels

	/**
	 * Funcion que configura todos los componentes y su correcta colocacion
	 */
	private void initComponents() {
		setTitle(mi.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_TITLE));
		setSize(new Dimension());
		setLayout(new GridBagLayout());
		GridBagConstraints gc = new GridBagConstraints();

		gc.insets = new Insets(5, 5, 5, 5);
		gc.fill = GridBagConstraints.HORIZONTAL;

		// Catalogo
		gc.gridx = 0;
		lblCatalogo = new JLabel(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_LBL_CATALOGO));
		add(lblCatalogo, gc);

		gc.gridx = 1;
		cboCatalogo = new JComboBox(Catalogo.values());
		add(cboCatalogo, gc);

		// Descripcion
		gc.gridx = 2;
		lblDescripcion = new JLabel(
				mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_LBL_DESCRIPCION));
		add(lblDescripcion, gc);

		gc.gridx = 3;
		gc.gridwidth = 2;
		txtDescripcion = new JTextField();
		add(txtDescripcion, gc);
		gc.gridwidth = 1;

		// Monto
		gc.gridy = 1;
		gc.gridx = 0;
		lblMonto = new JLabel(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_LBL_MONTO));
		add(lblMonto, gc);

		gc.gridx = 1;
		txtMonto = new JFormattedTextField(new NumberFormatter(NumberFormat
				.getNumberInstance(mi.getIdioma().getLocale())));
		add(txtMonto, gc);

		// Activo
		gc.gridx = 2;
		gc.gridwidth = 1;
		chkActivo = new JCheckBox(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_CHK_ACTIVO));
		add(chkActivo, gc);

		// Botones
		JPanel jpnl = new JPanel(new FlowLayout());

		btnAgregar = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_AGREGAR));
		jpnl.add(btnAgregar);

		btnEliminar = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_ELIMINAR));
		jpnl.add(btnEliminar);

		btnActualizar = new JButton(
				mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_ACTUALIZAR));
		jpnl.add(btnActualizar);

		btnCerrar = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_CERRAR));
		jpnl.add(btnCerrar);

		btnObtenerCat = new JButton(
				mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_OBTENER_CAT));
		jpnl.add(btnObtenerCat);

		btnObtenerTodos = new JButton(
				mi
						.obtenerEtiqueta(Etiqueta.ELEMENTO_CATALOGO_FRAME_BTN_OBTENER_TODOS));
		jpnl.add(btnObtenerTodos);

		gc.gridy = 2;
		gc.gridx = 0;
		gc.gridwidth = 5;
		add(jpnl, gc);
		gc.gridwidth = 1;

		// Tabla de resultados

		gc.gridy = 3;
		gc.gridwidth = 4;
		gc.weightx = 1.0;
		gc.weighty = 1.0;
		gc.fill = GridBagConstraints.BOTH;
		ecm = new ElementoCatalogoModel(0);
		tblElementoCatalogo = new JTable(ecm);
		tblElementoCatalogo
				.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		add(new JScrollPane(tblElementoCatalogo), gc);

		setClosable(false);
		setSize(WIDTH, HEIGHT);
	}// initComponents

	private class ElementoCatalogoModel extends AbstractTableModel {
		private Map<Point, Object> lookup;
		private final int rows;
		private final int columns;
		private final String headers[];

		public ElementoCatalogoModel(int rows) {
			this.rows = rows;
			this.headers = mi
					.obtenerEtiqueta(
							Etiqueta.ELEMENTO_CATALOGO_FRAME_TBL_ELEMENTOS_COLUMN_NAMES)
					.split(",");
			this.columns = headers.length;

			lookup = new HashMap<Point, Object>();
		}

		public int getColumnCount() {
			return columns;
		}

		public int getRowCount() {
			return rows;
		}

		public String getColumnName(int column) {
			return headers[column];
		}

		public Object getValueAt(int row, int column) {
			return lookup.get(new Point(row, column));
		}

		public void setValueAt(Object value, int row, int column) {
			if ((rows < 0) || (columns < 0)) {
				throw new IllegalArgumentException("Invalid row/column setting");
			}
			if ((row < rows) && (column < columns)) {
				lookup.put(new Point(row, column), value);
			}
		}
	}

	/**
	 * Funcion que valida que los campos requeridos del formulario
	 * 
	 * @throws AvException
	 */
	private void validarTextos() throws AvException {
		if (cboCatalogo.getSelectedIndex() < 0) {
			cboCatalogo.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.ELEMENTO_CATALOGO_CBO_CATALOGO));
		}
		if (txtDescripcion.getText() == null
				|| txtDescripcion.getText().trim().length() == 0) {
			txtDescripcion.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.ELEMENTO_CATALOGO_TXT_DESCRIPCION));
		}
		if (txtMonto.getText() == null
				|| txtMonto.getText().trim().length() == 0) {
			txtMonto.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.ELEMENTO_CATALOGO_TXT_MONTO));
		}
	}// validarTextos

	private ElementoCatalogo getElementoCatalogo() {
		if (elementoSeleccionado == null) {
			elementoSeleccionado = new ElementoCatalogo();
		}

		elementoSeleccionado.setCatalogo((Catalogo) cboCatalogo
				.getSelectedItem());
		elementoSeleccionado.setDescripcion(txtDescripcion.getText());
		elementoSeleccionado.setCosto(new Double(txtMonto.getText()));
		elementoSeleccionado.setActivo(chkActivo.isSelected());

		return elementoSeleccionado;
	}// getElementoCatalogo

	private void setElementoCatalogo(ElementoCatalogo ec) {
		if (ec != null) {
			elementoSeleccionado = ec;

			cboCatalogo.setSelectedItem(ec.getCatalogo());
			txtDescripcion.setText(ec.getDescripcion());
			txtMonto.setText(ec.getCosto() + "");
			chkActivo.setSelected(ec.isActivo());

		}
	}// setElementoCatalogo

	private void limpiarTextos() {
		cboCatalogo.setSelectedIndex(-1);
		txtDescripcion.setText("");
		txtMonto.setText("");
		chkActivo.setSelected(false);
	}// limpiarTextos

	/**
	 * Clase creada para la administracion de acciones
	 * 
	 * @author Emmanuel Alcantara Garces
	 * 
	 */
	private class BotonHandler implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent ev) {
			Object o = ev.getSource();
			if (o instanceof JButton) {
				if (o == btnCerrar) {
					dispose();
				} else if (o == btnActualizar) {
					try {
						validarTextos();
						actualizarElementoCatalogo();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}

				} else if (o == btnEliminar) {
					try {
						validarTextos();
						eliminarElementoCatalogo();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}
				} else if (o == btnAgregar) {
					try {
						validarTextos();
						agregarElementoCatalogo();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}
				} else if (o == btnObtenerCat) {
					obtenerCatalogoElementoCatalogo();
				} else if (o == btnObtenerTodos) {
					cargarElementoCatalogo();
				}
			}
		}// actionPerformed
	}// BotonHandler

	/**
	 * Funcion que agrega un elemento catalogo a partir de los datos capturados
	 * 
	 * @throws AvException
	 */
	private void agregarElementoCatalogo() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.AGREGAR_ELEMENTO_CATALOGO);
		elementoSeleccionado = new ElementoCatalogo();
		p.setValor(Tipo.INPUT, getElementoCatalogo());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarElementoCatalogo();
	}// agregarElementoCatalogo

	/**
	 * Funcion que actualiza un elemento catalogo con los datos capturados
	 * 
	 * @throws AvException
	 */
	private void actualizarElementoCatalogo() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.ACTUALIZAR_ELEMENTO_CATALOGO);
		p.setValor(Tipo.INPUT, getElementoCatalogo());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarElementoCatalogo();
	}// actualizarElementoCatalogo

	/**
	 * Funcion que elimina el elemento catalogo seleccionado
	 * 
	 * @throws AvException
	 */
	private void eliminarElementoCatalogo() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.ELIMINAR_ELEMENTO_CATALOGO);
		p.setValor(Tipo.INPUT, getElementoCatalogo());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarElementoCatalogo();
	}// eliminarElementoCatalogo

	/**
	 * Funcion que carga en la tabla todos los elementos catalogos registrados
	 * en el sistema
	 */
	private void cargarElementoCatalogo() {
		Parametro p = new Parametro();
		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			try {
				p.setAccion(CatalogoAcciones.OBTENER_TODOS_ELEMENTO_CATALOGO);
				p = AdministradorSesion.getInstance().getSesionActiva()
						.ejecutar(p);
				if (p.getValor(Tipo.OUTPUT) != null) {
					elementos = (ElementoCatalogo[]) p.getValor(Tipo.OUTPUT);
					ecm = new ElementoCatalogoModel(elementos.length);
					int row = 0;
					for (ElementoCatalogo e : elementos) {
						ecm
								.setValueAt(e.getCatalogo().getDescripcion(),
										row, 0);
						ecm.setValueAt(e.getDescripcion(), row, 1);
						ecm.setValueAt(e.getCosto(), row, 2);
						ecm.setValueAt(e.isActivo(), row, 3);
						row++;
					}
					tblElementoCatalogo.setModel(ecm);
				}
			} catch (AvException e) {
				ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR", e
						.getMessage(), null, null, e, Level.INFO, null);
				JXErrorPane.setDefaultLocale(mi.getIdioma().getLocale());
				JXErrorPane.showDialog(getParent(), info);
			}
		}
	}// cargarElementoCatalogo

	/**
	 * Funcion que carga en la tabla todos los elementos del catalogo
	 * seleccionado que se tienen registrados en el sistema
	 */
	private void obtenerCatalogoElementoCatalogo() {
		Parametro p = new Parametro();
		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			try {
				p
						.setAccion(CatalogoAcciones.OBTENER_CATALOGO_ELEMENTO_CATALOGO);
				p
						.setValor(Tipo.INPUT, (Catalogo) cboCatalogo
								.getSelectedItem());
				p = AdministradorSesion.getInstance().getSesionActiva()
						.ejecutar(p);
				if (p.getValor(Tipo.OUTPUT) != null) {
					elementos = (ElementoCatalogo[]) p.getValor(Tipo.OUTPUT);
					ecm = new ElementoCatalogoModel(elementos.length);
					int row = 0;
					for (ElementoCatalogo e : elementos) {
						ecm
								.setValueAt(e.getCatalogo().getDescripcion(),
										row, 0);
						ecm.setValueAt(e.getDescripcion(), row, 1);
						ecm.setValueAt(e.getCosto(), row, 2);
						ecm.setValueAt(e.isActivo(), row, 3);
						row++;
					}
					tblElementoCatalogo.setModel(ecm);
				} else {
					ecm = new ElementoCatalogoModel(0);
					ecm.setValueAt("", 0, 0);
					ecm.setValueAt("", 0, 1);
					ecm.setValueAt("", 0, 2);
					ecm.setValueAt("", 0, 3);
					tblElementoCatalogo.setModel(ecm);
				}
			} catch (AvException e) {
				ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR", e
						.getMessage(), null, null, e, Level.INFO, null);
				JXErrorPane.setDefaultLocale(mi.getIdioma().getLocale());
				JXErrorPane.showDialog(getParent(), info);
			}
		}
	}// cargarElementoCatalogo

	public static void main(String[] args) {
		JFrame tmp = new JFrame("ElementoCatalogoFrame");
		tmp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JDesktopPane desktop = new JDesktopPane();
		desktop.setBackground(Color.GRAY);
		desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
		tmp.setContentPane(desktop);

		ElementoCatalogoFrame ecf = new ElementoCatalogoFrame();
		ecf.setVisible(true);
		desktop.add(ecf);
		try {
			ecf.setSelected(true);
		} catch (PropertyVetoException e) {
		}
		tmp.setSize(new Dimension(ecf.getWidth() + 100, ecf.getHeight() + 100));
		tmp.setVisible(true);
	}// main

}// ElementoCatalogoFrame
